package com.sailing.xjpb.elasticsearch.util;

import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import com.google.common.collect.Lists;
import com.sailing.xjpb.common.EJBGenerator;
import com.sailing.xjpb.common.exception.BusinessException;
import jakarta.json.stream.JsonGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.io.ByteArrayOutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author luozy
 * createTime 2020/5/23
 */
@Slf4j
public class EsUtil {
    public static final String FORMART_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMART_YYYY_MM_DD = "yyyy-MM-dd";

    public static final String TYPE_1 = "doc";
    public static final String TYPE_2 = "_doc";
    public static final List<String> TYPES = Arrays.asList("doc", "_doc");

    private EsUtil() {
    }

    /**
     * Description:
     * CreateUser: 罗志银
     * CreateDate: 2020/08/10 11:37
     * <p>
     * EditDescription:
     * EditUser: 罗志银
     * EditDate: 2020/08/10 11:37
     *
     * @param beginTime   开始时间
     * @param endTime     结束时间
     * @param pattern     日期格式化格式
     * @param indexPrefix 数据文件前缀 索引名
     * @return List<String>
     */
    public static List<String> getIndexs(String beginTime, String endTime, String pattern, String indexPrefix) {
        return getIndexs(beginTime, endTime, pattern, FORMART_YYYY_MM_DD, indexPrefix);
    }

    /**
     * 根据两个时间获取连续 index
     *
     * @param beginTime:   开始时间
     * @param endTime:     结束时间
     * @param pattern:     index日期格式
     * @param indexPrefix: 索引名前缀
     * @return java.util.List<java.lang.String>
     * @author 罗志银
     * createDate 2023/2/27 12:47
     * <p>
     * editDescription
     * editUser
     * editDate 2023/2/27 12:47
     */
    public static List<String> getContinuationDayIndexs(String beginTime, String endTime, String pattern, String indexPrefix) {
        LocalDateTime start = com.sailing.xjpb.common.DateUtils.toLocalDateTime(com.sailing.xjpb.common.DateUtils.toDate(beginTime));
        LocalDateTime end = com.sailing.xjpb.common.DateUtils.toLocalDateTime(com.sailing.xjpb.common.DateUtils.toDate(endTime));
        return getContinuationDayIndexs(start, end, pattern, indexPrefix);
    }

    /**
     * 根据两个时间获取连续 index
     *
     * @param beginTime:   开始时间
     * @param endTime:     结束时间
     * @param pattern:     index日期格式
     * @param indexPrefix: 索引名前缀
     * @return java.util.List<java.lang.String>
     * @author 罗志银
     * createDate 2023/2/27 12:47
     * <p>
     * editDescription
     * editUser
     * editDate 2023/2/27 12:47
     */
    public static List<String> getContinuationDayIndexs(LocalDateTime beginTime, LocalDateTime endTime, String pattern, String indexPrefix) {
        List<String> indexs = new ArrayList<>();
        String s = com.sailing.xjpb.common.DateUtils.toString(beginTime, pattern);
        indexs.add(indexPrefix + "_" + s);
        Duration between = Duration.between(beginTime, endTime);
        if (between.isZero()) {
            return indexs;
        }
        Long dayLong = between.toDays();
        if (dayLong > 1000) {
            log.error("连续天数超过500，转成*模式");
            indexs.add(indexPrefix + "*");
            return indexs;
        }
        LocalDateTime temp = EJBGenerator.convert(beginTime, LocalDateTime.class);

        for (int i = 1; i <= dayLong; i++) {
            temp = temp.plusDays(1);
            String tempString = com.sailing.xjpb.common.DateUtils.toString(temp, pattern);
            indexs.add(indexPrefix + "_" + tempString);
        }
        return indexs;
    }

    /**
     * Description: 获取索引名称列表
     * CreateUser: 种传民
     * CreateDate:
     * <p>
     * EditDescription:
     * EditUser: 种传民
     * EditDate:
     *
     * @param beginTime    开始时间
     * @param endTime      结束时间
     * @param timePattern  时间格式
     * @param indexPattern 索引格式
     * @param indexPrefix  索引前缀
     * @return List<String>
     */
    public static List<String> getIndexs(String beginTime, String endTime, String timePattern, String indexPattern, String indexPrefix) {
        if (!indexPrefix.endsWith("_")) {
            indexPrefix = indexPrefix + "_";
        }
        List<String> indexs = Lists.newArrayList();
        if (StringUtils.isBlank(beginTime) && StringUtils.isBlank(endTime)) {
            indexs.add(indexPrefix + "*");
            return indexs;
        }
        if (StringUtils.isBlank(beginTime)) {
            beginTime = dateToStr(new Date());
        }
        if (StringUtils.isBlank(endTime)) {
            endTime = dateToStr(new Date());
        }

        LinkedList<String> tempIndexs = Lists.newLinkedList();
        try {
            int between = daysBetween(parseDate(beginTime, timePattern), parseDate(endTime, timePattern));

            if (between == 0) {
                indexs.add(indexPrefix + DateFormatUtils.format(parseDate(beginTime, timePattern), indexPattern));
                return indexs;
            }

            tempIndexs.add(DateFormatUtils.format(DateUtils.addDays(parseDate(beginTime, timePattern), -1),
                    indexPattern));
            for (int i = 0; i <= between; i++) {
                tempIndexs.addLast(DateFormatUtils.format(DateUtils.addDays(parseDate(beginTime, timePattern), i),
                        indexPattern));
            }
            tempIndexs.add(DateFormatUtils
                    .format(DateUtils.addDays(parseDate(beginTime, timePattern), between + 1), indexPattern));
            char[] firstIndexChar = tempIndexs.getFirst().toCharArray();
            char[] lastIndexChar = tempIndexs.getLast().toCharArray();
            StringBuilder sb = new StringBuilder(indexPrefix);
            if (firstIndexChar.length == lastIndexChar.length) {
                for (int i = 0; i <= firstIndexChar.length; i++) {
                    char a = firstIndexChar[i];
                    char b = lastIndexChar[i];
                    if (a == b) {
                        sb.append(a);
                    } else {
                        break;
                    }
                }
            }
            indexs.add(sb.append("*").toString());
        } catch (Exception e) {
            log.warn("根据时间段查询符合条件的索引index={}过程中出现错误：{}~{}", indexPrefix, beginTime, endTime);
            log.warn("根据时间段查询符合条件的索引过程中出现错误！", e);
            return Collections.singletonList(indexPrefix + "*");
        }
        return indexs;
    }

    /**
     * Description:
     * CreateUser: 罗志银
     * CreateDate: 2020/08/10 12:27
     * <p>
     * EditDescription:
     * EditUser: 罗志银
     * EditDate: 2020/08/10 12:27
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return int 计算2个时间之间相差几天
     */
    public static int daysBetween(Date beginTime, Date endTime) {
        Calendar beginDateCalender = Calendar.getInstance();
        beginDateCalender.setTime(beginTime);

        Calendar endDateCalender = Calendar.getInstance();
        endDateCalender.setTime(endTime);

        double beginLong = beginDateCalender.getTimeInMillis();
        double endLong = endDateCalender.getTimeInMillis();
        double divisor = (double) 1000 * 3600 * 24;
        double betweenDays = (endLong - beginLong) / divisor;
        return (int) Math.ceil(betweenDays);
    }

    /**
     * Description:
     * CreateUser: 罗志银
     * CreateDate: 2020/08/10 12:30
     * <p>
     * EditDescription:
     * EditUser: 罗志银
     * EditDate: 2020/08/10 12:30
     *
     * @param date 时间 时间格式化
     * @return String
     */
    public static String dateToStr(Date date) {
        return dateToStr(date, FORMART_YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * Description:
     * CreateUser: 罗志银
     * CreateDate: 2020/08/10 12:30
     * <p>
     * EditDescription:
     * EditUser: 罗志银
     * EditDate: 2020/08/10 12:30
     *
     * @param date      时间
     * @param formatStr 格式化格式 时间转字符串
     * @return String
     */
    public static String dateToStr(Date date, String formatStr) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStr);
        return simpleDateFormat.format(date);
    }


    /***
     * Description:
     * CreateUser: 种传民
     * CreateDate:
     * <p>
     * EditDescription:
     * EditUser: 种传民
     * EditDate:
     *
     * @param dateStr 时间字符串
     * @param formatStr 格式化格式 时间转字符串
     * @return Date
     */
    public static Date parseDate(String dateStr, String formatStr) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStr);
        try {
            return simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            throw BusinessException.businessError("请检查时间是否正确：{}", e);
        }
    }

    /**
     * Description: 打印语句
     * CreateUser: 种传民
     * CreateDate:
     * <p>
     * EditDescription:
     * EditUser: 种传民
     * EditDate:
     *
     * @param searchRequest 查询
     * @return String
     */
    public static String printEsBySearchRequest(SearchRequest searchRequest) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        JsonpMapper mapper = new JacksonJsonpMapper();
        JsonGenerator generator = mapper.jsonProvider().createGenerator(byteArrayOutputStream);
        mapper.serialize(searchRequest, generator);
        generator.close();
        return byteArrayOutputStream.toString();
    }

}
